
#include <string.h>
#include <stdio.h>
#include <stdarg.h>


#define tc_log(_fmt_, ...) \
        printf("[TC][%s:%d][%s] "_fmt_"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)
#define tc_log_err(_fmt_, ...) \
        printf("[TC][ERR][%s:%d][%s] "_fmt_"\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)


static void hexdump(const void *data, size_t size, const char *str, ...)
{
    char t_str[128];
    char hexByte[4];
    char hexLine[50];
    char charByte[2];
    char charLine[18];
    unsigned int i;

    va_list args;
    va_start(args, str);
    int len = vsnprintf(t_str, sizeof(t_str), str, args);
    va_end(args);
    printf("%.*s\r\n", len, t_str);

    for (i = 0; i < size; i++) {
        if (i % 16 == 0) {
            hexLine[0] = 0;
            charLine[0] = 0;
        }
        if (i % 16 == 8) {
            strcat(hexLine, " ");
            strcat(charLine, " ");
        }
        snprintf(hexByte, sizeof(hexByte), " %02x", ((unsigned char *) data)[i]);
        strcat(hexLine, hexByte);
        if (((unsigned char *) data)[i] < 32 || ((unsigned char *) data)[i] > 126) {
            strcat(charLine, ".");
        } else {
            snprintf(charByte, sizeof(charByte), "%c", ((unsigned char *) data)[i]);
            strcat(charLine, charByte);
        }
        if (i % 16 == 15 || i == size - 1) {
            printf("%04x:%-49s  %s\r\n", i & ~15, hexLine, charLine);
        }
    }
}

void PrintBoard(char** board, int boardSize, int* boardColSize)
{
    int i, j;

    tc_log("boardSize %d", boardSize);

    printf("[");
    for (i = 0; i < boardSize; ++i) {
        if (i != 0) {
            printf(" ");
        }
        printf("[");
        for (j = 0; j < boardColSize[i]; ++j) {
            if (j == 0) {
                printf("'%c'", board[i][j]);
            } else {
                printf(", '%c'", board[i][j]);
            }
        }
        if ((i + 1) == boardSize) {
            printf("]]\r\n");
        } else {
            printf("],\r\n");
        }
    }
}

int GetAroundM(char** board, int boardSize, int* boardColSize, int r, int c)
{
    int i, j;
    int num = 0;

    for (i = r - 1; i <= (r + 1); ++i) {
        if (i < 0 || i >= boardSize) {
            continue;
        }
        for (j = c - 1; j <= (c + 1); ++j) {
            if (j < 0 || j >= boardColSize[i]) {
                continue;
            }
            if (i == r && j == c) {
                continue;
            }

            if (board[i][j] == 'M') {
                num++;
            }
        }
    }

    return num;
}

/**
 * Return an array of arrays of size *returnSize.
 * The sizes of the arrays are returned as *returnColumnSizes array.
 * Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
 */
char** updateBoard(char** board, int boardSize, int* boardColSize, 
                int* click, int clickSize, int* returnSize, int** returnColumnSizes){
#if 1
    int i, num;
    char **B = (char **)malloc(sizeof(char *) * boardSize);
    int returnSizeB = boardSize;
    int *returnColumnSizesB = (int *)malloc(sizeof(int) * boardSize);

    *returnSize = returnSizeB;
    *returnColumnSizes = returnColumnSizesB;

    for (i = 0; i < boardSize; ++i) {
        B[i] = (char *)malloc(sizeof(char) * boardColSize[i]);
        memcpy(B[i], board[i], boardColSize[i]);
        returnColumnSizes[i] = boardColSize[i];
    }

    int cr = click[0];
    int cc = click[1];

    if (B[cr][cc] == 'M') {
        B[cr][cc] = 'X';
        return B;
    }

    num = GetAroundM(B, returnSizeB, returnColumnSizesB, cr, cc);
    if (num != 0) {
        B[cr][cc] = '0' + num;
        return B;
    }

    // TODO: dfs
    
#endif
}

int main(int argc, char const *argv[])
{
    tc_log("********************");
    tc_log("new start @ %s %s", __DATE__, __TIME__);
    tc_log("********************");

    int i;
    int boardSize = 4;

    char click[2] = {3, 0};

    char a[4][5] = {
        {'E', 'E', 'E', 'E', 'E'},
        {'E', 'E', 'M', 'E', 'E'},
        {'E', 'E', 'E', 'E', 'E'},
        {'E', 'E', 'E', 'E', 'E'}
    };

    tc_log("a[%d][%d] %c", 1, 2, a[1][2]);

    char **A = (char **)malloc(sizeof(char *) * 4);
    int *boardColSize = (int *)malloc(sizeof(int) * 4);

    for (i = 0; i < 4; ++i) {
        A[i] = (char *)malloc(sizeof(char) * 5);
        memcpy(A[i], a[i], 5);
        boardColSize[i] = 5;
    }

    // PrintBoard(A, boardSize, boardColSize);
    // tc_log("[%d][%d] M num %d", 1, 0, GetAroundM(A, boardSize, boardColSize, 1, 0));

    // int returnSize;
    // int *returnColumnSizes;
    // char **B = updateBoard(A, boardSize, boardColSize, click, sizeof(click), &returnSize, &returnColumnSizes);

    // PrintBoard(B, boareturnSizerdSize, returnColumnSizes);

    tc_log("exit");
    return 0;
}

